---
title: 领域建模实践
description: 事件风暴梳理了系统的行为需求。但其实还有些微妙的业务概念还没有澄清，这就要靠领域建模来完成了。
---
事件风暴梳理了系统的行为需求。但其实还有些微妙的业务概念还没有澄清，这就要靠领域建模来完成了。

<RedSpan>建立领域模型是 DDD 的核心</RedSpan>。要建好领域建模，需要理论和实践相结合。



## 领域建模中的一些基本概念

领域建模主要有两个目的：

* 将知识可视化，准确、深刻地反映领域知识，并且在业务和技术人员之间达成一致；
* 指导系统的设计和编码，也就是说，领域模型应该能够比较容易地转化成数据库模式和代码实现。

而我们建立的领域模型，主要是识别<RedSpan>领域对象（domain object），领域对象之间的关系，以及领域对象的关键属性</RedSpan>，必要的时候还要将<RedSpan>领域对象组织成模块</RedSpan>。

<RedSpan>系统中要处理的各种“事物“就是领域对象。</RedSpan>比如说项目、员工、账户等等。这些对象都反映了名词性的概念。


其中，有些名词化了的动词也是领域对象。比如说我们进行了一笔支付操作，并且想把这笔操作记录下来。这时，“支付”也是领域对象。支付本来是动词，但这里实际上是要把一笔支付的信息记录下来，在这里就把“支付”当名词用了。


<RedSpan>领域模型是用领域模型图来表达的，通常用 UML 来画。</RedSpan>UML 是 ”统一建模语言“的意思，英文是 Unified Modeling Language， 是面向对象建模的国际标准。其中，领域对象用下面这个符号来表示：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241130235447.png"/>

这个符号表示“员工”对象。其中第一栏是领域对象的名称，第二栏列出了对象的属性（attribute），姓名、性别都是员工的属性。


严格地说，在 UML 中，这个符号叫做“类”（class）。比如说，张三是员工，李四也是员工，我们可以说，员工指一类事物。这时我们可以用 UML 中的术语说，员工是领域对象的一个类，张三和李四是这个类的实例。在领域建模过程中，我们说领域对象时，有时指类，有时指实例，一般可以通过上下文来区分。

此外，<RedSpan>DDD 中将领域对象又分成实体（entity）和值对象（value object）</RedSpan>。值对象我们等到第二个迭代再讲，这个迭代我们只关心实体。我们前面说的“员工”“账户”等都是实体。



由类和他们之间的关系组成的图叫做类图，这也是领域建模里用到的最主要的图。

下面我们就开始通过画类图的方式进行领域建模。同样，你扮演架构师，我扮演产品经理。
## 领域建模(租户、组织和人员)
### 初步识别实体

我们可以从上节课中识别的领域名词入手，分成几部分来建模。我们先考虑租户、组织和人员。上节课的图是这样的：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201000258.png"/>

首先，你可以先假定每个领域名词都是一个实体，把它们用类的符号画出来。如下图：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201000319.png"/>

这就可以算作一张最简单的类图了。你可能注意到了，这里并没有写属性。其实，在领域建模阶段，我们主要关注的是实体和它们之间的关系。如果实体的名字已经能清晰说明实体的含义，那我们就不需要加属性了。如果名字还不足以充分表达含义，我们可以写几个关键属性，来辅助说明。

另外要注意，我们这里只是简单粗暴地假定了领域名词就是实体。通过后面的分析，我们还会发现，有些名词不是实体，有些要转换成其他形式。

### 识别一对一关联

现在，我们来识别实体之间的关系。先来看看租户和企业。

首先，你问我：“租户和企业这两个概念有没有关系呢？”我回答说：“肯定是有关系的。”于是你可以在它们两个之间画一条线，表示它们之间有关系。

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201002545.png"/>

然后，你又问了我两个有关业务的问题。第一个问题是：“一个租户最多可以对应几个企业？”我回答说：“只能对应一个企业。”于是，你在企业那一端写了一个 “1” 来表示。

然后你反过来问第二个问题：“一个企业可以作为几个租户？”我回答说：“一个企业也只能作为一个租户。”于是你在另一边也写上 “1” 。

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201002625.png"/>

这时，我们可以说，<RedSpan>租户和企业具有一对一的关系</RedSpan>。

这里的两个 “1” ，在 UML 中称为<RedSpan>多重性</RedSpan>（multiplicity）。那么，这种关系整体上呢，在 UML 的术语里叫做“关联”（association）。后面我们都用这种严格的说法，说成 <RedSpan>一对一关联</RedSpan>。

这时你可能又想到了一个问题：“为什么不把租户和企业合并成一个概念呢？”

在有些情况下，一对一的两个实体确实是可以合并的。这取决于这两个概念的关注点是否相同。

但在我们的需求里，租户关注的是客户和提供云应用的供应商之间的协议，背后隐含的需求可能是云平台要为这个客户分配多少硬件资源、怎样收费、提供哪个级别的备份等需求。假如这不是一个基于 SaaS 的应用，根本不会有租户的概念。

而另一方面，企业是组织结构管理中的一个概念，即使不基于 SaaS，企业这个概念也存在。所以这是两个不同关注点的概念，不应该合并。
### 识别一对多关联
下面我们再分析企业和开发中心的关联关系。这时你同样考虑了两个问题。首先，一个开发中心可以属于多少个企业呢？只能属于一个企业。这和上面的画法相同。

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201003126.png"/>
第二个问题是，一个企业可以有多少个开发中心？答案是可以有很多个。这可以在开发中心一端写一个 “*” 来表达。

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201003140.png"/>

这时，我们可以说，企业和开发中心具有一对多关联。

接着你用同样的方法画出了开发组，如下图：
<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201003211.png"/>

现在咱们来考虑部门。你可能会发现，部门这个词其实用得不太准确，因为开发组也可以认为是部门。其实按照这里的需求我们想表达的是财务部、人事部等区别于开发中心和开发组的部门。

然后你又问我了：“在业务上，怎么称呼这种区别于开发中心的部门呢？”我说：“业务上一般叫做直属部门。”于是你在图中增加了直属部门。

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201003304.png"/>


然后，你把员工也加上了。

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201003325.png"/>

就这个图的含义而言，一个员工可以属于开发组，也可以属于直属部门，好像已经满足了需求，但是仔细想一下，你可能就会发现两个问题。

第一个问题是，如果将来组织层级发生变化，比如说在开发中心和开发组之间又增加了一层开发团队；或者有些开发组不属于任何开发中心，而是直属企业，那么这个模型就要修改了。也就是说，<RedSpan>这个模型不容易适应组织层级的变化</RedSpan>。

第二个问题是，一个员工其实可以不属于开发组，而只属于开发中心，比如开发中心的主管就是这样。同理，企业总经理也只属于企业本身而不属于任何下属部门。那么为了表达这种关系，我们就要再增加两条表示关联的线。

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201003435.png"/>

线越多，图就越杂乱。也就是说，<RedSpan>这个模型不够简洁</RedSpan>。

那么怎么解决这两个问题呢？我们要对这个模型进行抽象。

### 进行抽象
你可能已经注意到了，企业、开发中心、开发组、直属部门，其实都是组织结构中的节点而已，从这一点来说，他们是有共性的。

于是，你问我：“既然它们有共性，能否起一个统一的名字呢？也就是说，企业、开发中心、开发组、直属部门，可以统称为什么呢？”我回答说：“在业务上可以统称为组织。”所以你把模型改成下面这个样子：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201003545.png"/>

由于开发中心、开发组等都是组织，所以只画出组织就可以了，模型图变得很简洁。但是你马上就发现，无法区分出一个组织到底是开发组还是开发中心了，也就是 <RedSpan>归纳了共性，但个性却丢了</RedSpan>。

这时你问我：“一个组织是开发中心，另一个是开发组，那么在业务术语上可以说，这两个组织具有不同的‘什么’呢？”我告诉你：“可以说，这两个组织具有不同的组织类别。

于是你画出下面的模型图。

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201003640.png"/>

也就是在这个模型中增加了一个组织类别的实体。企业、开发中心、直属部门等都是组织类别的实例。<RedSpan>一个组织类别下可以有多个组织，而一个组织只能属于一个组织类别</RedSpan>。比如说，开发组这个组织类别，下面可以有开发一组、开发二组等等很多具体的组织。

为了怕以后读这个模型图的人不理解什么是组织类别，我们还可以加一个注释，用来举例说明有哪些组织类别。在 UML 中，注释用折角的矩形表示，和被注释的实体之间用虚线连接，如下图：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201003752.png"/>

### 识别自关联


然后，你又发现，这个图还不能表示企业、开发中心、开发组等之间的上下级关系。这可以用组织这个实体上的“自关联”来表达。画出来是下面这个样子：


<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201003857.png"/>

在这个图中，组织实体上有一个自己到自己的一对多关联。这个关联翻译成自然语言可以这么说：<RedSpan>一个组织可以有多个组织作为自己的下级；而一个组织只能有一个组织作为自己的上级</RedSpan>。这样就表现出了上下级的层级关系。这种一对多的自关联，实际上表达的是一种树形结构。

另外，在这个自关联的两端，有上级和下级两个词。它们在 UML 里称为“角色”（role）。也就是说，在这个关联的 “1” 端的组织充当上级这个角色，在另一端充当下级角色。如果没有这两个角色名称的话，我们就不知道是一个上级有多个下级，还是一个下级有多个上级了。

### 增加约束
另外，为了说明“一个开发中心下面有多个开发组，而不是一个开发组下面有多个开发中心”这个业务规则，我又另外加了一个注释。如下图：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201004040.png"/>

你可能发现了，这个注释和上一个有些区别，它的内容用大括号括起来了。在 UML 中，用大括号括起来的内容称为“约束”（constraint）。和一般性的注释不同，<RedSpan>凡是约束，必须在程序中的某个地方进行实现。约束也是一种业务规则</RedSpan>，应该加进前面讲过的业务规则表。

不过，细心的你又发现，关于租户还有两个问题没有在这个模型中表达出来。

第一个问题是，没有说明“只有企业才能作为租户，其他类别的组织不能作为租户”；另一个问题是，作为多租户系统，其实每一个实体都应该与租户有一个关联，说明这个实体是属于哪一个租户的，这样才能把不同租户的数据区分开。但是，如果把这些关联都画出来，模型图中的线条就会太多了，变得非常混乱。


于是，你又添加了一个注释和一个约束来说明上面两个问题。有了这个注释，租户和组织上原来的那个关联也可以省去了。如下图：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201004447.png"/>

你看，这个模型既简洁又灵活，解决了我们前面说的员工实体上有多个关联以及组织层级难以扩展这两个问题。

### 识别多对多

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201004527.png"/>

你问我：“管理员和人事人员其实也是员工是吧？”我说：“是。”但这时你可能会纠结，这两个东西到底是不是实体呢？

于是你又问我：“从业务的角度，可不可以认为管理员和人事人员其实都是员工担任的岗位呢？”我说：“这个理解很正确。”于是，你就画出了下面的图：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201004624.png"/>

这个图表示，一个员工可以担任多个岗位，而一个岗位也可以有多个员工担任。<RedSpan>员工和岗位之间是“多对多”关联</RedSpan>。我表示，这完全符合我对业务的理解。


### 更丰富的多重性
现在，我们再看一下多重性问题。前面说过，关联两端的 “1” 或者 “*” 称为“多重性”。比如说下图中组织和员工之间就是一对多关联：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201004713.png"/>

你还可以问两个问题，把多重性进一步细化。

第一个问题是：“一个组织可以没有任何员工吗？”我回答：“业务上允许先建立一个组织，但暂时不往里面分配任何员工。”那么，你可以在员工那一端的 “*” 前面加上 “0..”，变成 “0..*” 。如下图：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201004745.png"/>

这里的 “0..*” 我们也可以这样理解：<RedSpan>一个组织最少有 0 个员工，最多可以有很多员工</RedSpan>。


类似地，你可以从关联的另一个方向再问第二个问题：“一个员工可以不属于任何组织吗？”我回答：“不行。一个员工必须属于一个组织。”于是，你把另一端改成了 “1..1” 。


<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201004821.png"/>

这里的 “1..1” 表示，一个员工最少要属于一个组织，最多也只能属于一个组织。

通过上面的方法，多重性的语义就变得更加丰富了。在实际项目中，团队可以自行决定，把多重性识别得粗一点，只写 “1”和 “*” ；还是细一点，识别出 “1..1” “0..*” 等等。一般来说，如果目的是在短时间内大致了解业务概念，就可以做粗一点；如果是为了指导具体的开发，则可以做细一点。在后面的例子中，我们都按照比较细的方法来做。

丰富了多重性以后，整个模型成为了下面的样子：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201004901.png"/>

现在，我们终于完成了关于租户、组织和员工的领域模型。
## 领域建模(项目管理)
<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201005705.png"/>

我们先假定每个名词都是一个实体，然后再把这些实体一个个加到已有的模型图里。初步识别出的实体有下面这些：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201005723.png"/>

### 处理客户
我们首先来处理客户实体。按照需求，每个客户有一个客户经理负责。你和我确认了一下：“客户经理也是员工对吧？”我说：“是的。”于是你把客户添加到了模型里，如下图：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201144654.png"/>

这里你把客户经理当作了一个角色，员工和客户的关联翻译成自然语言就是“一个员工可以充当多个客户的客户经理，而一个客户有且仅有一个员工作为他的客户经理”。

### 处理合同

完成了对客户的建模，我们开始处理合同实体。根据需求，“每个合同都有一个销售人员负责”，于是，你画出了下面的模型图：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201144822.png"/>

你有些疑惑：“客户经理是不是也是销售人员呢？”我说：“是的。”于是你意识到：“销售人员应该也是员工的一种岗位，并且在与客户的关联中，充当了客户经理这个角色。那么，类似地，销售人员又充当合同的什么角色呢？”我说：“就叫合同经理吧。”


于是，你修改了销售人员这个角色的名字，并且在岗位的注释中增加了销售人员。此外，你又增加了“只有销售人员才能作客户经理” 以及“只有销售人员才能作合同经理”这两条业务规则。

现在的模型图如下：
<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201145030.png"/>

### 处理项目
接着，你又用类似的方法，增加了项目实体：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201145324.png"/>

### 考虑为项目分配员工

现在我们考虑“为项目分配员工”和“员工退出项目”这两个需求。

首先，我在图里面的员工和项目之间增加了一个表示“员工被分配到项目上”的关联，同时把“一个员工预计的投入百分比不能大于百分之百”的规则也标注出来。

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201145502.png"/>

这时候，员工和项目之间就有了两个不同的关联。原来那个一对多关联表达的是“员工充当项目经理”的关系。

另外，我们新增了一个关联，表示分配员工的关系。一个员工可以被分配到多个项目上，一个项目上又可以有多个员工，因此两者是“多对多”关联。在这个关联的员工一端，写上了项目成员这个角色。也就是员工充当了项目的项目成员。

在这里我们可以看到，<RedSpan>两个实体之间，可以有多个关联。不同的关联代表不同含义，数量关系也可以不同，可以用角色名来区分</RedSpan>


然后你问我：“这里有一个关于投入百分比的规则，那么投入百分比这个属性应该记录在哪个实体上呢？”这时候我们发现了一个尴尬的问题，这个百分比既不能记录在员工实体上，也不能记录在项目实体上。

这是因为，只有员工和项目建立了项目成员这一关联的时候，记录投入百分比才是有意义的，也就是说，这个属性应该记录在这个多对多关联上。那么这在 UML 中怎么表达呢？

于是，我把模型改成了下面的样子：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201150347.png"/>

这时候，原来的**项目成员**角色演变成了一个独立的实体，来表达员工和项目之间的多对多关联。预计**投入百分比**也就自然放在这个实体里面了。

注意，这时候，员工和项目成员之间的关联是一对多，项目和项目成员之间也是一对多。然后我总结道：“<RedSpan>任何多对多关联，总能用类似的方法，通过引入一个表示关联的实体，拆成两个一对多的关联。</RedSpan>”


接着，你又注意到一个问题，一个员工可以分配到一个项目上，然后退出项目，然后再一次分配到这个项目上，所以，我们就应该用时间段来记录员工参与项目的历史。

考虑到时间因素，有关投入百分比的业务规则可以进一步明确为“**在任何时刻**，一个人的预计投入百分比总和不能大于百分之百。”此外，从逻辑上，还可以识别一条规则**一个员工在同一个项目上的时间段不能重叠**。

于是你这样改进了模型：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201151358.png"/>

### 处理登记工时
接下来，为了处理报工时的需求，你又增加了工时记录实体，以及相关的业务规则：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201152147.png"/>

同样，我们可以把工时记录看作员工和项目之间的一种多对多关系。

### 识别操作
经过上面的梳理，我们已经把剩余的模型梳理得差不多了。但是，在事件风暴中咱们还遗留了一个问题：怎么处理客户经理上级、销售人员上级和项目经理上级这几个概念？现在看来，它们不太像是独立的实体，而更像是某种关系。

经过讨论我们发现，客户经理、销售人员、项目经理，无非都是员工，所以他们的上级，其实都可以归纳为 <RedSpan>取员工上级</RedSpan>这个操作。然后我们讨论出了取员工上级的逻辑：

* 如果员工不是所属组织的负责人，那么这个组织的负责人就是员工的上级；
* 如果员工就是所属组织的负责人，那么这个组织的上级组织的负责人就是这个员工的上级。

你看，在上述逻辑中，我们又引入了一个**组织负责人**的概念。可以认为，负责人是员工在与组织的关联中充当的一种角色。

基于这些理解，我把模型进一步完善了一下：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201154549.png"/>

在这个模型中，有几个要注意的地方：

第一，为了表达组织的负责人，我在员工和组织之间又增加了一个一对多关联，表示“一个员工可以不作任何组织的负责人，也可以作多个组织的负责人；而一个组织可以暂时没有负责人，但最多只能有一个负责人。”

现在，组织和员工之间就有两种不同的关联了，分别用了成员和负责人两种角色来区分。

第二，我们在员工实体上增加了取上级这个操作。<RedSpan>操作（operation）在 UML 里也叫方法（method）。对象的属性是静态的值，而操作是动态的逻辑</RedSpan>。在 UML 中，操作用“操作名 + 括号”的方式表示，括号中可以写参数。

第三，我们用一个注解说明了取上级这个操作的业务逻辑。



## 划分模块
现在，我们的领域模型已经覆盖了事件风暴中发现的所有领域概念，但是，你是不是觉得这个图已经有点乱，不太容易理解了呢？

之所以这个图不容易理解，是因为很多实体和关联混杂在一起，形成了一个“蜘蛛网”。但人的认知能力是有限的，面对这样一张复杂的对象网络，就产生了认知过载（cognitive overload）。

解决这一问题的方法就是“模块化”。也就是说，把模型中的业务概念组织成若干高内聚的模块（module），而模块之间尽量低耦合。

在 UML 中，可以用包来表示模块。包的符号是下面这样：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201154829.png"/>


包的内部可以包含实体，也可以包含另外的包。在 UML 中，任何需要对元素进行分组的场合，都可以使用包。经过一番讨论，我们采用如下方式划分模块：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201194705.png"/>

也就是说，我们把模型分成了 4 个模块，分别是租户管理、组织管理、项目管理和工时管理。是不是感觉清晰多了？
:::tip
划分模块有时没有绝对“正确”的标准。这里的“工时管理”，看起来是可以放在“项目管理”，但另一方面，放在“组织管理”似乎也合理，因为这里考虑的是某个“人”的工时。面对这种两可的局面，那么单独作为一个模块可能合理一些。

工时记录没有和项目成员关联在一起，而是和成员关联在一起,是因为我们关心的是一个员工的工时，哪怕不在同一个项目。
:::
有了模块，我们就可以从两个层面理解模型。

**第一个是宏观层面**。宏观层面只关心模型中有哪些模块，以及模块间的依赖关系，不关心模块内部的细节。为了达到这个目的，我们可以画出更宏观的包图。像下面这样：
<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201195150.png"/>

这里我们又引入了一个新的符号，就是带箭头的虚线。这在 UML 中表示依赖（dependency）关系，箭头由依赖方指向被依赖方。

从图中我们看到：

首先，所有模块都依赖租户管理。这是因为，为了将不同租户的数据区别开来，每个模块中的实体都要说明自己是哪个租户的；


其次，项目管理依赖组织管理。这是因为项目经理、项目成员等概念都依赖于组织管理中的员工；

还有，工时管理既依赖组织管理又依赖项目管理。这是因为工时管理要说明（组织管理中的）哪个员工在（项目管理中的）哪个项目上投入了多少工时。


我们要注意，依赖关系和前面讲的关联关系是不一样的。<RedSpan>关联表示的是数据上的导航关系</RedSpan>。例如，当我们说组织和员工之间具有一对多关联的时候，就意味着，由组织可以找到下面的员工，由员工也可以找到所属的组织。

依赖表示的意思更为广泛。**如果 A、B 两个元素，有了 A 才能有 B，那么就可以说 B 依赖于 A**。

我们可以认为关联是一种特殊的依赖关系，但依赖还有别的形式，比如说项目管理模块依赖于组织管理模块，两者之间未必有直接的数据导航关系，可能只是项目管理调用组织管理，获得需要的数据。

:::tip
模块和代码有直接的对应关系（模块就是代码中的包）
:::

**理解模型的第二个层面是微观层面**，也就是深入到模块内部，了解实体和关联等等的细节。

通过这种分而治之的方法，我们可以在一定程度上管理复杂性，解决认知过载的问题。<RedSpan>如果模型更加复杂，那么还要进一步采用限界上下文</RedSpan>来处理，这个会在第三个迭代再介绍。


现在，领域模型基本完成了。为了完善开发过程，我们还要再进行两个实践：一个是完善业务规则，另一个是建立词汇表。

## 完善业务规则
我们在做事件风暴时就开始识别业务规则了，在领域建模中又识别出了更多的规则，所以现在我们需要把这些规则补充到业务规则表之中，如下表：
<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201204543.png"/>
其中，从 R006 开始，是我们领域建模阶段新识别出的领域规则。

## 建立词汇表

接着我们来建立词汇表，也就是把事件风暴和领域模型中重要的词汇列成表。为什么要建立词汇表呢？主要是有两个作用。

首先，我们需要通过词汇表来**规范领域模型中的词汇**。同一个词，可能会在领域模型中出现多次，时间久了，就可能不一致，因此需要进一步规范。

第二，是可以**用于后续编程中的命名**。按照 DDD 的要求，程序中的各种命名也需要统一，并且需要与领域模型中保持一致。我们会在词汇表中列出英文全称和缩写，以达到这个目的。

词汇表是保证统一语言的重要手段。

目前为止的重要词汇，都列到下面这张词汇表里了。

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201204723.png"/>



## 总结
从事件风暴识别出的领域名词出发，开始进行领域建模。首先假定每个领域名词都是一个实体。然后识别实体之间的关联。关联可以分为三种：一对一、一对多和多对多。而这些不同的关联，可以用多重性来表达。

假设有 A 和 B 两类实体，你可以通过问四个问题，来把多重性搞清楚：

* 一个实体 A 最多可以对应多少个实体 B？
* 一个实体 A 最少可以对应多少个实体 B？
* 一个实体 B 最多可以对应多少个实体 A？
* 一个实体 B 最少可以对应多少个实体 A？

还有一种关联是实体自身上的“自关联”，可以表达由某种实体组成的树状或网状结构。这比一般的关联稍微难理解一些，但熟练以后就容易了。

在建模过程中，我们还可以通过“抽象”，找出领域名词中并没有直接揭示出来的实体。例如把企业、开发中心等抽象成组织和组织类别，把管理员、人事人员等抽象成岗位。这样的模型更能反映出业务的本质，从而更加灵活。通过这种抽象的过程，使模型和业务不仅仅是“形似”，更是“神似”。

我们还可以通过增加注释和约束，使模型中的业务知识更加丰富和准确。其中，约束是一种特殊的注释，它的内容必须以某种形式在代码或数据库中实现。约束也属于我们在之前说的业务规则，需要补充到业务规则表中去。

对“多对多”关联的理解：<RedSpan>我们可以通过引入一个表示关联的实体，将一个多对多关联拆成两个一对多关联</RedSpan>。

我们还通过取员工上级的逻辑，学习了为实体添加操作。当模型变得比较复杂时，可以把模型划分成多个模块，使模型更容易理解。

在建立完领域模型之后，我们还进行了两项实践：完善 <RedSpan>业务规则和建立词汇表</RedSpan>。很多朋友过去并不重视这两个实践，然而，它们对落实 DDD 实践，具有很重要的作用，一定要引起重视。

:::tip 一个多对多关联可以拆成两个一对多关联，那么你觉得什么时候应该拆，什么时候不拆呢？
1. 多对多关系存在业务规则时，需要拆分出来一个承载的实体，变成两个一对多的关系；
2. 多对多关系存在专门的业务属性
3. 多对多关系本身也是业务关注的一个独立概念
:::

https://juejin.cn/post/7186685036127748155

https://juejin.cn/post/7182111319967924282